package com.mezz.bones.framework.mybatis.helper;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;

import lombok.extern.slf4j.Slf4j;

/**
 * @Author: zhuang
 * @Date: 2024/12/24 14:27
 * @Description: 事务管理助手类，支持自定义事务配置和回滚机制
 * @Version: 1.0
 **/
@Slf4j
@Component
public class TransactionManagerHelper {

    private final PlatformTransactionManager transactionManager;

    public TransactionManagerHelper(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    /**
     * 执行自定义事务
     * @param isolationLevel 事务隔离级别 TransactionDefinition.ISOLATION_DEFAULT
     * @param propagationBehavior 事务传播行为 TransactionDefinition.PROPAGATION_REQUIRED
     * @param transactionLogic 由调用者传入的具体事务逻辑方法
     */
    public void executeTransaction(int isolationLevel, int propagationBehavior, TransactionLogic transactionLogic) {
        TransactionTemplate template = new TransactionTemplate(transactionManager);
        template.setIsolationLevel(isolationLevel); // 设置隔离级别
        template.setPropagationBehavior(propagationBehavior); // 设置传播行为

        template.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    // 执行调用者传入的事务逻辑
                    transactionLogic.execute();

                    // 如果一切正常，事务将在方法结束时自动提交
                } catch (Exception e) {
                    // 如果发生异常，标记事务回滚
                    status.setRollbackOnly();
                    log.error("事务发生异常,已回滚", e);
                    throw e; // 重新抛出异常，事务回滚
                }
            }
        });
    }

    /**
     * 使用默认事务配置执行事务
     * @param transactionLogic 由调用者传入的具体事务逻辑方法
     */
    public void executeTransaction(TransactionLogic transactionLogic) {
        // 默认使用 ISOLATION_DEFAULT 和 PROPAGATION_REQUIRED
        executeTransaction(TransactionDefinition.ISOLATION_DEFAULT, TransactionDefinition.PROPAGATION_REQUIRED, transactionLogic);
    }

    /**
     * 设置事务超时
     * @param timeout 超时时间，单位秒
     * @param transactionLogic 由调用者传入的具体事务逻辑方法
     */
    public void executeTransactionWithTimeout(int timeout, TransactionLogic transactionLogic) {
        TransactionTemplate template = new TransactionTemplate(transactionManager);
        template.setTimeout(timeout); // 设置超时时间（秒）

        template.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    // 执行调用者传入的事务逻辑
                    transactionLogic.execute();
                } catch (Exception e) {
                    status.setRollbackOnly();
                    log.error("事务发生异常,已回滚", e);
                    throw e;
                }
            }
        });
    }


    /**
     * 判断当前是否存在活动事务
     * @return 如果存在活动事务则返回 true，否则返回 false
     */
    public boolean isTransactionActive() {
        return TransactionSynchronizationManager.isActualTransactionActive();
    }

    /**
     * 事务逻辑接口（执行事务逻辑代码）
     */
    @FunctionalInterface
    public interface TransactionLogic {
        void execute();
    }


    /**
     * 注册事务完成后执行的逻辑 事务提交/事务回滚
     * 可以把业务无关事务的逻辑写到此回调中 比如消息推送等一些不是特别重要的数据
     * @param afterCompletionAction
     */
    public void registerAfterCompletion(TransactionLogic afterCompletionAction) {

        if (!isTransactionActive()) {
            return;
        }
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCompletion(int status) {
                if (status == TransactionSynchronization.STATUS_COMMITTED) {
                    try {
                        // 无论提交或回滚，执行回调逻辑
                        afterCompletionAction.execute();
                        log.info("事务提交成功，执行回调逻辑");
                    } catch (Exception e) {
                        log.error("事务完成后执行的回调逻辑发生异常", e);
                    }
                } else if (status == TransactionSynchronization.STATUS_ROLLED_BACK) {
                    log.warn("事务回滚");
                }

            }
        });
    }



}
